package com.yupi.yuoj.service.impl;

import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yupi.yuoj.common.ErrorCode;
import com.yupi.yuoj.constant.CommonConstant;
import com.yupi.yuoj.exception.BusinessException;
import com.yupi.yuoj.mapper.QuestionSubmitMapper;
import com.yupi.yuoj.model.dto.questionSubmit.QuestionSubmitAddRequest;
import com.yupi.yuoj.model.dto.questionSubmit.QuestionSubmitQueryRequest;
import com.yupi.yuoj.model.entity.Question;
import com.yupi.yuoj.model.entity.QuestionSubmit;
import com.yupi.yuoj.model.entity.User;
import com.yupi.yuoj.model.enums.QuestionSubmitLanguageEnum;
import com.yupi.yuoj.model.enums.QuestionSubmitStatusEnum;
import com.yupi.yuoj.model.vo.QuestionSubmitVO;
import com.yupi.yuoj.service.QuestionService;
import com.yupi.yuoj.service.QuestionSubmitService;
import com.yupi.yuoj.service.UserService;
import com.yupi.yuoj.utils.SqlUtils;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;


/**
 * @author tiankui
 * @description 针对表【question_submit(题目提交)】的数据库操作Service实现
 * @createDate 2024-05-08 16:58:17
 */
@Service
@RequiredArgsConstructor
public class QuestionSubmitServiceImpl extends ServiceImpl<QuestionSubmitMapper, QuestionSubmit>
        implements QuestionSubmitService {

    private final QuestionService questionService;
    private final UserService userService;

    /**
     * 题目提交业务方法实现
     *
     * @param questionSubmitAddRequest
     * @param loginUser
     * @return Integer
     * @author Manner
     * @date 2024/5/14 11:02
     */
    @Override
    public Long doQuestionSubmit(QuestionSubmitAddRequest questionSubmitAddRequest, User loginUser) {
        //校验编程语言是否合法支持
        String language = questionSubmitAddRequest.getLanguage();
        QuestionSubmitLanguageEnum languageName = QuestionSubmitLanguageEnum.getEnumByValue(language);
        if (languageName == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "不支持的编程语言!");
        }
        Long questionId = questionSubmitAddRequest.getQuestionId();
        //根据实体判断题目是否存在
        Question question = questionService.getById(questionId);
        if (question == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        //收集一次题目提交所需要的信息
        QuestionSubmit questionSubmit = QuestionSubmit.builder()
                .userId(loginUser.getId())
                .questionId(questionId)
                .language(questionSubmitAddRequest.getLanguage())
                .code(questionSubmitAddRequest.getCode())
                .status(QuestionSubmitStatusEnum.WAITING.getValue())
                .judgeInfo("{}")
                .build();
        //保存题目提交记录
        boolean save = this.save(questionSubmit);
        //提交失败就抛出业务异常终止
        if (!save) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "提交题目失败!");
        }
        //提交成功就直接返回这次题目提交的ID编号
        return questionSubmit.getId();
    }

    /**
     * 根据查询调教构建QueryWrapper对象
     *
     * @param questionSubmitQueryRequest 查询条件对象
     * @return QueryWrapper<QuestionSubmit>
     * @author Manner
     * @date 2024/5/15 12:35
     */
    @Override
    public QueryWrapper<QuestionSubmit> getQueryWrapper(QuestionSubmitQueryRequest questionSubmitQueryRequest) {
        QueryWrapper<QuestionSubmit> queryWrapper = new QueryWrapper<>();
        if (questionSubmitQueryRequest == null) {
            return queryWrapper;
        }
        String language = questionSubmitQueryRequest.getLanguage();
        Integer status = questionSubmitQueryRequest.getStatus();
        Integer questionId = questionSubmitQueryRequest.getQuestionId();
        Integer userId = questionSubmitQueryRequest.getUserId();
        String sortField = questionSubmitQueryRequest.getSortField();
        String sortOrder = questionSubmitQueryRequest.getSortOrder();

        queryWrapper.eq(ObjUtil.isNotEmpty(language), "language", language);
        queryWrapper.eq(QuestionSubmitStatusEnum.getEnumByValue(status) != null, "status", status);
        queryWrapper.eq(ObjUtil.isNotEmpty(questionId), "questionId", questionId);
        queryWrapper.eq(ObjUtil.isNotEmpty(userId), "userId", userId);
        queryWrapper.eq("isDelete", false);
        queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC),
                sortField);
        return queryWrapper;
    }


    /**
     * 查询单个题目提交记录脱敏后的数据
     *
     * @param questionSubmit
     * @param loginUser
     * @return QuestionSubmitVO
     * @author Manner
     * @date 2024/5/10 17:32
     */
    @Override
    public QuestionSubmitVO getQuestionSubmitVO(QuestionSubmit questionSubmit, User loginUser) {
        QuestionSubmitVO questionSubmitVO = QuestionSubmitVO.objToVo(questionSubmit);
        //只有本人和管理员能够看到题目提交记录的代码,再次脱敏
        if (loginUser.getId() != questionSubmit.getUserId() && !userService.isAdmin(loginUser)) {
            questionSubmitVO.setCode(null);
        }
        return questionSubmitVO;
    }

    /**
     * 查询题目提交记录脱敏后的分页信息
     *
     * @param questionSubmitPage
     * @param loginUser
     * @return Page<QuestionSubmitVO>
     * @author Manner
     * @date 2024/5/15 12:44
     */
    @Override
    public Page<QuestionSubmitVO> getQuestionSubmitVOPage(Page<QuestionSubmit> questionSubmitPage, User loginUser) {
        //获取分页对象中存储的数据
        List<QuestionSubmit> questionSubmitList = questionSubmitPage.getRecords();
        //新建脱敏类型的Page对象并获取未脱敏类型Page对象的信息
        Page<QuestionSubmitVO> questionSubmitVOPage = new Page<>(
                questionSubmitPage.getCurrent(),
                questionSubmitPage.getSize(),
                questionSubmitPage.getTotal()
        );
        //如果未脱敏的数据集合为空,那么就直接返回没有数据的脱敏类型Page对象
        if (CollectionUtils.isEmpty(questionSubmitList)) {
            return questionSubmitVOPage;
        }
        //循环调用判断 单个数据 是否需要再脱敏 的 方法进行所有数据的再脱敏判断
        List<QuestionSubmitVO> questionSubmitVOList = questionSubmitList.stream()
                .map(questionSubmit ->
                        getQuestionSubmitVO(questionSubmit, loginUser)
                )
                .collect(Collectors.toList());
        questionSubmitVOPage.setRecords(questionSubmitVOList);
        return questionSubmitVOPage;
    }
}




